package pa14.asmt.asmt3.main;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import soot.Body;
import soot.BodyTransformer;
import soot.G;
import soot.SootMethod;
import soot.Value;
import soot.toolkits.graph.ExceptionalUnitGraph;

public class TaintVariableTransformer extends BodyTransformer {

	public TaintVariableTransformer() {
		super();
	}

	@SuppressWarnings("rawtypes")
	@Override
	protected void internalTransform(Body body, String arg1, Map arg2) {
		
		boolean verbose = true;
		
		
		//	 get all parameters so as to set the initial
		Set<Value> params = new HashSet<Value>();
		SootMethod thisMethod = body.getMethod(); 
		int paramCount = thisMethod.getParameterCount();
		for(int i=0; i<paramCount; i++){
			Value v = body.getParameterLocal(i);
			params.add(v);
		}
		if(verbose)
			G.v().out.println("\nSearching method: " + thisMethod.getName());
		
		//	Look for parameters, as they will be the taints
		if(verbose)
			G.v().out.println("\tParameter List:");
		if(params.isEmpty()){
			if(verbose)
				G.v().out.println("\t\tNo parameters!");
		}else{
			if(verbose)
				for(Value l : params){
					G.v().out.println("\t\tParam: " + l.toString() + "\t\tType: " + l.getType().toString());
			}
		}
		
		TaintVariableAnalysis t = new TaintVariableAnalysis(new ExceptionalUnitGraph(body), params, false);
		
		Set<Value> taintedVars = t.getTaintedVars();
		Set<Value> taintedLiveVarsAtSink = t.getTaintedVarsLiveAtSink();
		
		if(verbose)
			G.v().out.println("\tTainted variables reaching Sink:");
		if(taintedVars.isEmpty()){
			if(verbose)
				G.v().out.println("\t\tNo Tainted variables reaching Sink!");
		}else{
			if(verbose)
				for(Value v : taintedVars){
					G.v().out.println("\t\t" + v + "\t\tType: " + v.getType().toString());
			}
		}
		if(verbose)
			G.v().out.println("\tGathering all tainted variables live at sink:");
		if(taintedLiveVarsAtSink.isEmpty()){
			if(verbose)
				G.v().out.println("\t\tNo Tainted variables live at Sink!");
		}else{
			if(verbose)
				for(Value v : taintedLiveVarsAtSink){
					G.v().out.println("\t\t" + v + "\t\tType: " + v.getType().toString());
			}
		}
		

	}

}
